package com.tqjc.system.core.pipeline.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.tqjc.system.common.constant.AddTaskConstant;
import com.tqjc.system.common.entity.BO.AddBusinessTaskInfo;
import com.tqjc.system.common.entity.BO.MaterialSpanBO;
import com.tqjc.system.common.entity.BO.TankCarTaskInfoBO;
import com.tqjc.system.common.enums.TankCarNoEnum;
import com.tqjc.system.common.enums.TaskStatusEnum;
import com.tqjc.system.core.pipeline.BusinessProcess;
import com.tqjc.system.core.pipeline.ProcessContext;
import com.tqjc.system.core.pipeline.util.AddTaskUtil;
import com.tqjc.system.core.pipeline.util.ScanUtils;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.system.entity.SysAddPrimaryTaskEntity;
import com.tqjc.system.system.service.SysAddPrimaryTaskService;
import com.tqjc.system.system.service.SysAreaInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 86195
 * @version 1.0
 * @description 设置槽车位置服务
 * @date 2023/10/17 11:03
 */
@Service
@Slf4j
public class SetTankCarPositionAction implements BusinessProcess<AddBusinessTaskInfo> {

    @Autowired
    private SysAreaInfoService areaInfoService;

    @Autowired
    private SysAddPrimaryTaskService primaryTaskService;

    public static Lock lock = new ReentrantLock();

    @Override
    public void process(ProcessContext<AddBusinessTaskInfo> context) {
        AddBusinessTaskInfo taskInfo = context.getProcessModel();
        String taskId = taskInfo.getTaskId();
        String tankCarNo = taskInfo.getTankCarNo();
        log.info("加料任务taskId：{}设置槽车位置任务开始",taskId);
        //翻转主表任务的状态
        SysAddPrimaryTaskEntity sysAddPrimaryTask = SysAddPrimaryTaskEntity.builder().idKey(Long.valueOf(taskId))
                .status(TaskStatusEnum.STATUS_DOING.getStatus()).startDate(new Date()).build();
        primaryTaskService.updateById(sysAddPrimaryTask);
        //储存对象中,所需去跨集合
        context.setBreakFlag(true);
        //更新槽车扫描动作标识
        ScanUtils.setTankCarScanActFinish(TankCarNoEnum.getEnumByCarNo(tankCarNo),false);
        List<String> taskSpanList = taskInfo.getTaskSpanList();
        if(CollUtil.isNotEmpty(taskSpanList)){
            //原始对象中，存在则直接去对应的跨即可
            String spanNo = taskSpanList.get(0);
            //添加至槽车队列中
            TankCarTaskInfoBO infoBO = TankCarTaskInfoBO.builder().taskType(AddTaskConstant.TANK_CAR_TASK_TYPE_ADD).spanNo(spanNo).build();
            AddTaskConstant.TANK_CAR_QUEUE_MAP.get(tankCarNo).add(infoBO);

            //删除
            //组装数据对象，流传下个节点
            buildContext(context,taskInfo,taskSpanList,spanNo);
            return;
        }
        List<String> taskMaterialList = context.getProcessModel().getTaskMaterialList();
        //1.查看物料分布的跨区
        //1.1 查看废钢跨任务物料数量
        int wasteSteelNum = areaInfoService.queryMaterialNum(AddTaskConstant.WASTE_STEEL_SPAN_NO,taskMaterialList);
        //1.2查看渣跨任务物料数量
        int dregsSteelNum = areaInfoService.queryMaterialNum(AddTaskConstant.DREGS_STEEL_SPAN_NO,taskMaterialList);

        if (wasteSteelNum == 0 && dregsSteelNum == 0){
            //两跨都无对应的任务物料，任务失败
            log.info("加料任务taskId：{}设置槽车位置任务失败，两跨均无任务物料",taskId);
            primaryTaskService.update(new LambdaUpdateWrapper<SysAddPrimaryTaskEntity>()
                    .set(SysAddPrimaryTaskEntity::getUpdateDate, LocalDateTime.now())
                    .set(SysAddPrimaryTaskEntity::getStatus, TaskStatusEnum.STATUS_ERROR.getStatus())
                    .set(SysAddPrimaryTaskEntity::getErrMsg,"两跨均无任务物料")
                    .eq(SysAddPrimaryTaskEntity::getIdKey,taskId));
            return;

        }

        if(taskSpanList == null){
            taskSpanList = new ArrayList<>(2);
        }
        if(wasteSteelNum == 0){
            //废钢跨没有任务物料，只能去渣跨
            taskSpanList.add(AddTaskConstant.DREGS_STEEL_SPAN_NO);
        } else if(dregsSteelNum == 0){
            //渣跨没有任务物料，只能去废钢跨
            taskSpanList.add(AddTaskConstant.WASTE_STEEL_SPAN_NO);
        } else {
            //两跨均由任务物料
            taskSpanList.add(AddTaskConstant.WASTE_STEEL_SPAN_NO);
            taskSpanList.add(AddTaskConstant.DREGS_STEEL_SPAN_NO);
        }

        //2.查看两个跨哪个天车空闲
        try {

            lock.lock();
            if(taskSpanList.size() >= 2){
                //两跨均有任务物料的，须查看那跨天车空闲  没有空闲则需要等待天车
                MaterialSpanBO freeSpan = AddTaskUtil.getFreeSpan();
                while (freeSpan == null){
                    Thread.sleep(5*1000);
                    freeSpan = AddTaskUtil.getFreeSpan();
                }
                String spanNo = freeSpan.getSpanNo();
                AddTaskUtil.updateSpanNoStatus(spanNo,AddTaskConstant.SPAN_STATUS_WORK);
                //将任务添加至槽车任务队列中
                TankCarTaskInfoBO infoBO = TankCarTaskInfoBO.builder().taskType(AddTaskConstant.TANK_CAR_TASK_TYPE_ADD).spanNo(spanNo).build();
                Queue<TankCarTaskInfoBO> queue = AddTaskConstant.TANK_CAR_QUEUE_MAP.get(tankCarNo);
                queue.add(infoBO);
                buildContext(context,taskInfo,taskSpanList,spanNo);

            } else {
                //直接去对应物料任务跨
                String spanNo = taskSpanList.get(0);
                MaterialSpanBO freeSpan = AddTaskUtil.getFreeSpan(spanNo);
                while (freeSpan == null){
                    Thread.sleep(5*1000);
                    freeSpan = AddTaskUtil.getFreeSpan();
                }
                //将任务添加至槽车任务队列中
                TankCarTaskInfoBO infoBO = TankCarTaskInfoBO.builder().taskType(AddTaskConstant.TANK_CAR_TASK_TYPE_ADD).spanNo(spanNo).build();
                Queue<TankCarTaskInfoBO> queue = AddTaskConstant.TANK_CAR_QUEUE_MAP.get(tankCarNo);
                queue.add(infoBO);
                AddTaskUtil.updateSpanNoStatus(spanNo,AddTaskConstant.SPAN_STATUS_WORK);
                buildContext(context,taskInfo,taskSpanList,spanNo);
            }
            lock.unlock();
        } catch (Exception e){
            log.error("加料任务出现异常",e);

        }

        log.info("加料任务taskId：{}设置槽车位置任务结束",taskId);

    }



    /**
     * 对原来跨集合进行操作，移除已移动的spanNo
     * @param context
     * @param taskInfo
     * @param spanList
     */
    private void buildContext(ProcessContext<AddBusinessTaskInfo> context,AddBusinessTaskInfo taskInfo,
                              List<String> spanList,String spanNo){
        taskInfo.setWorkingSpanNo(spanNo);
        spanList.removeIf(e ->spanNo.equals(e));
        taskInfo.setTaskSpanList(spanList);
        context.setProcessModel(taskInfo);
        context.setBreakFlag(false);
    }
}
